package com.clp.util.hutool.core.bean;

import com.clp.util.ClassUtil;
import com.clp.util.hutool.core.lang.Assert;

import java.util.Map;

/**
 * 动态Bean，通过反射对Bean的相关方法做操作<br>
 * 支持Map和普通Bean
 *
 * @author Looly
 * @since 3.0.7
 */
public class DynaBean {
    private final Class<?> beanClass;
    private final Object bean;

    public DynaBean(Object bean) {
        Assert.notNull(bean);
        if (bean instanceof DynaBean) {
            bean = ((DynaBean) bean).getBean();
        }
        this.bean = bean;
        this.beanClass = ClassUtil.getClass(bean);
    }

    @SuppressWarnings("unchecked")
    public <T> T getBean() {
        return (T) this.bean;
    }

    /**
     * 获得字段对应值
     *
     * @param <T>       属性值类型
     * @param fieldName 字段名
     * @return 字段值
     * @throws BeanException 反射获取属性值或字段值导致的异常
     */
    @SuppressWarnings("unchecked")
    public <T> T get(String fieldName) throws BeanException {
        if (Map.class.isAssignableFrom(beanClass)) {
            return (T) ((Map<?, ?>) bean).get(fieldName);
        } else {
            final PropDesc prop = BeanUtil.getBeanDesc(beanClass).getProp(fieldName);
            if (null == prop) {
                throw new BeanException("No public field or get method for {}", fieldName);
            }
            return (T) prop.getValue(bean);
        }
    }

    /**
     * 检查是否有指定名称的bean属性
     *
     * @param fieldName 字段名
     * @return 是否有bean属性
     * @since 5.4.2
     */
    public boolean containsProp(String fieldName) {
        return null != BeanUtil.getBeanDesc(beanClass).getProp(fieldName);
    }
}
